home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Applications / QuArK / plugins / mapmakeprism.py < prev    next >
Text File  |  2004-01-05  |  19KB  |  499 lines

  1. #-------------------------------------------------------------------------------
  2. #      Module:         mapmakeprism.py
  3. #      Subsystem:      mapmakeprism
  4. #      Program:        mapmakeprism
  5. #      Copyright (c) 1998 - Descartes Systems Sciences
  6. #
  7. # Code review:
  8. #
  9. # tiglari's remarks on some suggested code changes, prefaced by tig:
  10. #
  11. #
  12. #-------------------------------------------------------------------------------
  13. # $Header: /cvsroot/quark/runtime/plugins/mapmakeprism.py,v 1.11 2003/03/24 08:57:15 cdunde Exp $
  14.  
  15. Info = {
  16.    "plug-in":       "Make n sided prism",
  17.    "desc":          "Make an n sided prism from user supplied specs",
  18.    "date":          "2000.06.??",
  19.    "author":        "ax2grind",
  20.    "author e-mail": "ax2grind@altavista.com",
  21.    "original author":        "Tim Smith",
  22.    "original author e-mail": "etsmith@mindspring.com",
  23.    "quark":         "Version 6.x"
  24. }
  25.  
  26.  
  27. import quarkpy.qmenu
  28. import math
  29. import quarkx
  30. import quarkpy.qmacro
  31. import quarkpy.qtoolbar
  32. import quarkpy.mapsearch
  33. import quarkpy.mapbtns
  34. from quarkpy.maputils import *
  35. import mapsearch1
  36.  
  37.  
  38. class MakePrismDlg(quarkpy.qmacro.dialogbox):
  39.     # Dialog layout
  40.     size = (290, 322)
  41.     dfsep = 0.4     # separation at 40% between labels and edit boxes
  42.     dlgflags = FWF_KEEPFOCUS + FWF_NORESIZE
  43.  
  44.     dlgdef = """
  45.         {
  46.             Style = "15"
  47.             Caption = "Make an N-Sided Prism"
  48.  
  49.             tex: =
  50.             {
  51.                 Txt = "Prism texture:"
  52.                 Typ = "ET"
  53.                 SelectMe = "1"
  54.             }
  55.  
  56.             vertex: =
  57.             {
  58.                 Typ = "X"
  59.                 Txt = "Start prism..."
  60.                 Cap = "on a vertex"
  61.             }
  62.  
  63.             sides: =
  64.             {
  65.                 Txt = "Number of sides"
  66.                 Typ = "EF1"
  67.                 Min = '5'
  68.             }
  69.  
  70.             radius: =
  71.             {
  72.                 Txt = "Radius of prism"
  73.                 Typ = "EF"
  74.                 Hint = "Distance(s) from center to outside edge."
  75.                  $0D$0D"There are four ways of specifying the radius:"
  76.                     $0D"'<r>' - The same radius all over"
  77.                     $0D"'<x> <y>' - X-axis and Y-axis radiuses"
  78.                     $0D"'<lx> <ly> <ur>' - Lower X/Y-axis radiuses, and Upper radius"
  79.                     $0D"'<lx> <ly> <ux> <uy>' - Lower X/Y-axis radiuses, and Upper X/Y-axis radiuses"
  80.                  $0D$0D"Examples:"
  81.                     $0D"'128' - Will give a uniform cylinder, 128 units in radius"
  82.                     $0D"'128 64' - Will give an oval cylinder, 128 X-radius and 64 Y-radius"
  83.                     $0D"'128 64 96' - Will give an oval cylinder at the bottom, and a uniform cylinder at the top"
  84.                     $0D"'128 64 64 128' - Will give an oval cylinder at the bottom, and the same at top but twisted"
  85.             }
  86.  
  87.             hollow: =
  88.             {
  89.                 Txt = "Hollow of prism"
  90.                 Typ = "EF"
  91.                 Hint = "Distance(s) from center to inside edge."
  92.                     $0D"Must be zero or lower than the 'Radius of prism' values,"
  93.                     $0D"and 'Pie-slices' must be marked for hollow to have any effect."
  94.                  $0D$0D"If any of the values are negative, they will be subtracted"
  95.                     $0D"from the 'Radius', and used as inner-radius."
  96.                  $0D$0D"The same four ways of specifying the radius, apply to"
  97.                     $0D"this, as with 'Radius of prism'."
  98.             }
  99.  
  100.             height: =
  101.             {
  102.                 Txt = "Height of prism"
  103.                 Typ = "EF1"
  104.             }
  105.  
  106.             offset: =
  107.             {
  108.                 Txt = "Slant of prism"
  109.                 Typ = "EF"
  110.                 Hint = "X- and Y-offset between the lower- and upper-centerpart of the cylinder"
  111.                  $0D$0D"Examples:"
  112.                     $0D"'0' - No slant/skew/offset of the prism"
  113.                     $0D"'+64' - Offset the upper-centerpart of the cylinder by; (64,64)"
  114.                     $0D"'+32 -16' - Offset the upper-centerpart of the cylinder by; (32,-16)"
  115.             }
  116.  
  117.             gridsize: =
  118.             {
  119.                 Txt = "Size of grid"
  120.                 Typ = "EF1"
  121.                 Hint = "Vertices aligned to this grid."
  122.             }
  123.  
  124.             slice: =
  125.             {
  126.                 Typ = "X"
  127.                 Txt = "Pie-slices"
  128.                 Cap = "Yes, make me some slices"
  129.             }
  130.  
  131.             shareface: =
  132.             {
  133.                 Typ = "X"
  134.                 Txt = "Share Faces"
  135.                 Cap = "Yes, Top and Bottom"
  136.             }
  137.  
  138.             stair: =
  139.             {
  140.                 Typ = "X"
  141.                 Txt = "Staircase:"
  142.                 Cap = "Yes, make me some stairs."
  143.             }
  144.  
  145.             ramp: =
  146.             {
  147.                 Typ = "X"
  148.                 Txt = "Ramp:"
  149.                 Cap = "Yes, make me a ramp."
  150.             }
  151.  
  152.  
  153.  
  154.             sep: = { Typ ="S" Txt=""}
  155.  
  156.             MakePrism:py = {Txt="" }
  157.  
  158.             close:py = {Txt="" }
  159.         }
  160.     """
  161.  
  162.     def __init__(self, form, editor):
  163.         # General initialization of some local values
  164.         self.editor = editor
  165.         self.sellist = self.editor.visualselection()
  166.  
  167.         # Create the data source
  168.         src = quarkx.newobj(":")
  169.  
  170.         # Based on the textures in the selections, initialize the from and to textures
  171.         texlist = quarkx.texturesof(editor.layout.explorer.sellist)
  172.         if len(texlist) == 1:
  173.             src["tex"] = texlist[0]
  174.         else:
  175.             src["tex"] = quarkx.setupsubset()["DefaultTexture"]
  176.  
  177.         # Populate the other values
  178.         if (quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Sides"] is None):
  179.             src["vertex"]      = ""
  180.             src["sides"]       = 6,
  181.             src["radius"]      = 64, 64, 64, 64,
  182.             src["hollow"]      = 0, 0, 0, 0,
  183.             src["height"]      = 128,
  184.             src["offset"]      = 0, 0,
  185.             src["gridsize"]    = 0,
  186.             src["slice"]       = ""
  187.             src["shareface"]   = ""
  188.             src["stair"]       = ""
  189.             src["ramp"]        = ""
  190.         else:
  191.             src["vertex"]      = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Vertex"]
  192.             src["sides"]       = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Sides"]
  193.             src["radius"]      = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Radius"]
  194.             src["hollow"]      = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Hollow"]
  195.             src["height"]      = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Height"]
  196.             src["offset"]      = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Offset"]
  197.             src["gridsize"]    = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Gridsize"]
  198.             src["slice"]       = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Slice"]
  199.             src["shareface"]   = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Shareface"]
  200.             src["stair"]       = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Stair"]
  201.             src["ramp"]        = quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Ramp"]
  202.  
  203.         # Create the dialog form and the buttons
  204.         quarkpy.qmacro.dialogbox.__init__(self, form, src,
  205.             close = quarkpy.qtoolbar.button(
  206.                 self.close,
  207.                 "close this box",
  208.                 ico_editor, 0,
  209.                 "Close"),
  210.             MakePrism = quarkpy.qtoolbar.button(
  211.                 self.MakePrism,
  212.                 "make prism",
  213.                 ico_editor, 3,
  214.                 "Make Prism"))
  215.  
  216.  
  217.  
  218.     def MakePrism(self, btn):
  219.         # Commit any pending changes in the dialog box
  220.         quarkx.globalaccept()
  221.  
  222.         # Gather information about what is to be created
  223.         tex     = self.src["tex"]
  224.         sides   =(self.src["sides"])[0]
  225.  
  226.         try:
  227.             # Set; Down-Outer-Radius-X, Down-Outer-Radius-Y, Up-Outer-Radius-X, Up-Outer-Radius-Y
  228.             value = self.src["radius"]
  229.             dorx = dory = uorx = uory = value[0]
  230.             if len(value) > 1:
  231.                 dory = uory = value[1]
  232.             if len(value) > 2:
  233.                 uorx = uory = value[2]
  234.             if len(value) > 3:
  235.                 uory = value[3]
  236.         except:
  237.             raise "Failure in 'Radius of prism' values"
  238.         if (dorx < 0 or dory < 0 or uorx < 0 or uory < 0):
  239.             raise "Negative values in 'Radius of prism' not allowed"
  240.  
  241.         try:
  242.             # Set; Down-Inner-Radius-X, Down-Inner-Radius-Y, Up-Inner-Radius-X, Up-Inner-Radius-Y
  243.             value = self.src["hollow"]
  244.             dirx = diry = uirx = uiry = value[0]
  245.             if len(value) > 1:
  246.                 diry = uiry = value[1]
  247.             if len(value) > 2:
  248.                 uirx = uiry = value[2]
  249.             if len(value) > 3:
  250.                 uiry = value[3]
  251.             # If negative values, compute real radius from center
  252.             if (dirx < 0):
  253.                 dirx = dorx + dirx
  254.             if (diry < 0):
  255.                 diry = dory + diry
  256.             if (uirx < 0):
  257.                 uirx = uorx + uirx
  258.             if (uiry < 0):
  259.                 uiry = uory + uiry
  260.         except:
  261.             raise "Failure in 'Hollow of prism' values"
  262.         if (dirx < 0 or diry < 0 or uirx < 0 or uiry < 0):
  263.             raise "Negative values in 'Hollow of prism' will result in illegal brushes"
  264.  
  265.         value   = self.src["height"]
  266.         height  = value[0] / 2
  267.  
  268.         try:
  269.             value = self.src["offset"]
  270.             offsetX = offsetY = value[0]
  271.             if len(value) > 1:
  272.                 offsetY = value[1]
  273.         except:
  274.             raise "Failure in 'Offset of prism' values"
  275.  
  276.         gridsize    = (self.src["gridsize"])[0]
  277.         slice       = self.src["slice"] is not None
  278.         shareface   = self.src["shareface"] is not None
  279.         stair       = self.src["stair"] is not None
  280.         ramp        = self.src["ramp"] is not None
  281.  
  282.         # Save the settings...
  283.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Vertex"]       = self.src["vertex"]
  284.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Sides"]        = self.src["sides"]
  285.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Radius"]       = self.src["radius"]
  286.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Hollow"]       = self.src["hollow"]
  287.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Height"]       = self.src["height"]
  288.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Offset"]       = self.src["offset"]
  289.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Gridsize"]     = self.src["gridsize"]
  290.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Slice"]        = self.src["slice"]
  291.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Shareface"]    = self.src["shareface"]
  292.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Stair"]        = self.src["stair"]
  293.         quarkx.setupsubset(SS_MAP, "Options")["MakePrism_Ramp"]         = self.src["ramp"]
  294.  
  295.         z_axis = quarkx.vect(0,0,1)
  296.         
  297.         # Create the prism
  298.         if slice:
  299.             p = quarkx.newobj("n-prism:g");
  300.         else:
  301.             p = quarkx.newobj("n-prism:p");
  302.  
  303.         # Create the top and bottom face
  304.         up = quarkx.newobj("up:f")
  305.         up["v"] = (-uorx+offsetX,-uory+offsetY,height, 128-uorx+offsetX,-uory+offsetY,height, -uorx+offsetX,128-uory+offsetY,height)
  306.         up["tex"] = tex
  307.         down = quarkx.newobj("down:f")
  308.         down["v"] = (-dorx,128-dory,-height, 128-dorx,128-dory,-height, -dorx,-dory,-height)
  309.         down["tex"] = tex
  310.         # attach in simplest case
  311.         if (slice and shareface and not stair) or not slice:
  312.                 p.appenditem(up)
  313.                 p.appenditem(down)
  314.  
  315.         # Create the sides
  316.         angle = math.pi/2
  317.         step = math.pi*2/sides
  318.         if (self.src["vertex"] is None):
  319.             angle = angle-step/2
  320.         caseup = casedown = slantup = slantdown = i = 0
  321.  
  322.         while i < sides:
  323.             # Compute the information about the side
  324.             v1 = self.ComputePoint(angle-step,  dorx, dory, gridsize, -height)
  325.             v2 = self.ComputePoint(angle,       dorx, dory, gridsize, -height)
  326.             v3 = self.ComputePoint(angle-step,  uorx, uory, gridsize,  height)
  327.             v4 = self.ComputePoint(angle,       uorx, uory, gridsize,  height)
  328.  
  329.             # Create the face
  330.             f = quarkx.newobj("outside:f")
  331.             f["v"] = (v1.x,v1.y,v1.z, v2.x,v2.y,v2.z, v3.x+offsetX,v3.y+offsetY,v3.z)
  332.             f["tex"] = tex
  333.  
  334.             if not slice:
  335.                 p.appenditem(f)
  336.             else:
  337.                 p1 = quarkx.newobj("prism-slice:p");
  338.                 p1.appenditem(f)
  339.  
  340.                 v5 = self.ComputePoint(angle,       dirx, diry, gridsize, -height)
  341.                 v6 = self.ComputePoint(angle-step,  dirx, diry, gridsize, -height)
  342.                 v7 = self.ComputePoint(angle,       uirx, uiry, gridsize,  height)
  343.                 v8 = self.ComputePoint(angle-step,  uirx, uiry, gridsize,  height)
  344.  
  345.                 f = quarkx.newobj("clockside:f")
  346.                 f["v"] = (v6.x,v6.y,v6.z, v1.x,v1.y,v1.z, v8.x+offsetX,v8.y+offsetY,v8.z)
  347.                 f["tex"] = tex
  348.                 p1.appenditem(f)
  349.  
  350.                 if stair:
  351.                     caseup = height*2/sides*i
  352.                     if shareface:
  353.                         casedown = height*2/sides*(sides-i-1)
  354.  
  355.                 if ramp:
  356.                     slantup = height*2/sides
  357.                     if shareface:
  358.                         slantdown = slantup
  359.  
  360.                     f = quarkx.newobj("farside:f")
  361.                     f["v"] = (v2.x,v2.y,v2.z, v6.x,v6.y,v6.z, v4.x+offsetX,v4.y+offsetY,v4.z)
  362.                     f["tex"] = tex
  363.                     p1.appenditem(f)
  364.  
  365.                     f = quarkx.newobj("up:f")
  366.                     f["v"] = (v3.x+offsetX,v3.y+offsetY,v3.z-caseup-slantup, v4.x+offsetX,v4.y+offsetY,v4.z-caseup, v8.x+offsetX,v8.y+offsetY,v8.z-caseup-slantup)
  367.                     f["tex"] = tex
  368.                     p1.appenditem(f)
  369.  
  370.                     f = quarkx.newobj("down:f")
  371.                     f["v"] = (v1.x,v1.y,v1.z+casedown-slantdown, v6.x,v6.y,v6.z+casedown-slantdown, v2.x,v2.y,v2.z+casedown)
  372.                     f["tex"] = tex
  373.                     p1.appenditem(f)
  374.  
  375.                     p.appenditem(p1);
  376.                     p1 = quarkx.newobj("prism-slice:p");
  377.  
  378.                     f = quarkx.newobj("nearside:f")
  379.                     f["v"] = (v6.x,v6.y,v6.z, v2.x,v2.y,v2.z, v8.x+offsetX,v8.y+offsetY,v8.z)
  380.                     f["tex"] = tex
  381.                     p1.appenditem(f)
  382.  
  383.                 f = quarkx.newobj("counterside:f")
  384.                 f["v"] = (v2.x,v2.y,v2.z, v5.x,v5.y,v5.z, v4.x+offsetX,v4.y+offsetY,v4.z)
  385.                 f["tex"] = tex
  386.                 p1.appenditem(f)
  387.  
  388.                 if (dirx or diry or uirx or uiry) != 0:
  389.                     f = quarkx.newobj("inside:f")
  390.                     f["v"] = (v5.x,v5.y,v5.z, v6.x,v6.y,v6.z, v7.x,v7.y,v7.z)
  391.                     f["tex"] = tex
  392.                     p1.appenditem(f)
  393.  
  394.                 if (not shareface and not stair) or stair:
  395. #                    f = quarkx.newobj("up:f")
  396. #                    f["v"] = (v7.x+offsetX,v7.y+offsetY,v7.z, v8.x+offsetX,v8.y+offsetY,v8.z, v4.x+offsetX,v4.y+offsetY,v4.z)
  397. #                    f["tex"] = tex
  398.                     f = up.copy()
  399.                     if stair:
  400.                        f.translate(-caseup*z_axis)
  401.                     p1.appenditem(f)
  402.  
  403.  
  404. #                    f = quarkx.newobj("down:f")
  405. #                    f["v"] = (v5.x,v5.y,v5.z+casedown, v2.x,v2.y,v2.z+casedown, v6.x,v6.y,v6.z+casedown-slantdown)
  406. #                    f["tex"] = tex
  407.                     f = down.copy()
  408.                     p1.appenditem(f)
  409.  
  410.  
  411.                 p.appenditem(p1);
  412.  
  413.  
  414.             # Next point
  415.             angle = angle - step
  416.             i = i + 1
  417.  
  418.  
  419.  
  420.         # Remove borken polys and faces then Drop the items
  421.  
  422.         p.rebuildall()
  423.         list = p.findallsubitems("", ':p')+p.findallsubitems("", ':f')
  424.         list = filter(lambda p: p.broken, list)
  425.         faces = list
  426.         for face in faces:
  427.             if face.broken:
  428.                 face.parent.removeitem(face)
  429.  
  430.  
  431.         quarkpy.mapbtns.dropitemsnow(self.editor, [p], "make n sided prism")
  432.         return
  433.  
  434.  
  435.     def ComputePoint(self, angle, radiusX, radiusY, gridsize, z):
  436.         # Compute the vertex
  437.         if radiusX > 0:
  438.             x = math.cos(angle) * radiusX
  439.         elif radiusX < 0:
  440.             x = math.cos(angle) ** 3 * math.fabs(radiusX)
  441.         else:
  442.             x = 0
  443.         if radiusY > 0:
  444.             y = math.sin(angle) * radiusY
  445.         elif radiusY < 0:
  446.             y = math.sin(angle) ** 3 * math.fabs(radiusY)
  447.         else:
  448.             y = 0
  449.         if gridsize != 0:
  450.             x = quarkx.rnd(x / gridsize) * gridsize
  451.             y = quarkx.rnd(y / gridsize) * gridsize
  452.         return quarkx.vect(x, y, z)
  453.  
  454.  
  455. def MakePrismClick(m):
  456.     # Function to start the dialog
  457.     editor = mapeditor()
  458.     if editor is None:
  459.         return
  460.     MakePrismDlg(quarkx.clickform, editor)
  461.  
  462.  
  463. # Register the replace texture menu item
  464. quarkpy.mapcommands.items.append(quarkpy.qmenu.sep) # separator
  465. quarkpy.mapcommands.items.append(quarkpy.qmenu.item("&Make Prism", MakePrismClick, "|Make Prism:\n\nThis opens a dialog window for your input to create a prism of various types as well as texture selection.|intro.mapeditor.menu.html#makeprism"))
  466.  
  467. #----------- REVISION HISTORY ------------
  468. #
  469. # $Log: mapmakeprism.py,v $
  470. # Revision 1.11  2003/03/24 08:57:15  cdunde
  471. # To update info and link to infobase
  472. #
  473. # Revision 1.10  2003/02/01 01:04:41  cdunde
  474. # Reactivate ramp selection and add script
  475. # to remove newly created broken polys and faces.
  476. #
  477. # Revision 1.8  2001/06/17 21:10:57  tiglari
  478. # fix button captions
  479. #
  480. # Revision 1.7  2001/03/07 20:16:16  tiglari
  481. # removed ramp checkbox (for now, till it works)
  482. #
  483. # Revision 1.6  2001/02/28 09:45:18  tiglari
  484. # fixed `stairs' option bug (ramp still has problems)
  485. #
  486. # Revision 1.5  2001/01/27 18:25:29  decker_dk
  487. # Renamed 'TextureDef' -> 'DefaultTexture'
  488. #
  489. # Revision 1.4  2000/12/19 21:07:42  decker_dk
  490. # Ax2Grind's MapMakePrism.py changes
  491. #
  492. # Revision 1.3  2000/06/03 10:25:30  alexander
  493. # added cvs headers
  494. #
  495. # 2000-04-29 Decker; Added functionality to create cylinder-walls, with indent.
  496. #            Loads/Saves used settings in SETUP.QRK
  497. # 1999-04-15 Decker; Added functionality to create pie-slices, and face-sharing
  498. #            of top and bottom face, if pie-slices are choosen.
  499.